<template>
  <!-- 人脸识别测试 -->
  <div>
    <div>
      <video class="video" ref="faceVideo"></video>
      <canvas width="256px" height="256px" class="canvas" ref="faceCanvas" />
    </div>
    <button class="test-btn" @click="gatherFaceInfo">开始识别</button>
  </div>
</template>

<script>
import axios from 'axios';
export default {
  name: 'gatherFace',
  data() {
    return {
      faceCtx: null,
      faceVideo: null,
      faceCanvas: null
    };
  },
  methods: {
    init() {
      // 人脸
      this.faceCanvas = this.$refs.faceCanvas;
      this.faceCtx = this.faceCanvas.getContext('2d');
      this.faceVideo = this.$refs.faceVideo;
    },
    // 构造媒体对象
    initMediaDevices() {
      if (navigator.mediaDevices === undefined) {
        navigator.mediaDevices = {};
      }

      if (navigator.mediaDevices.getUserMedia === undefined) {
        navigator.mediaDevices.getUserMedia = constraints => {
          const getUserMedia =
            navigator.webkitGetUserMedia || navigator.mozGetUserMedia;

          if (!getUserMedia) {
            return Promise.reject(
              new Error('getUserMedia is not implemented in this browser')
            );
          }

          return new Promise((resolve, reject) => {
            getUserMedia.call(navigator, constraints, resolve, reject);
          });
        };
      }
    },
    // 开启媒体采集设备
    openMedia(constraints) {
      return navigator.mediaDevices
        .getUserMedia(constraints)
        .then(
          stream => {
            return stream;
          },
          err => {
            alert(`${err.name}: ${err.message}`);
            return 'fail';
          }
        )
        .catch(err => {
          alert(`${err.name}: ${err.message}`);
        });
    },
    // 将base64集合转成file集合
    transformToFileList(list) {
      //将base64转换为blob
      const _dataURLtoBlob = dataurl => {
        let arr = dataurl.split(','),
          mime = arr[0].match(/:(.*?);/)[1],
          bstr = atob(arr[1]),
          n = bstr.length,
          u8arr = new Uint8Array(n);
        while (n--) {
          u8arr[n] = bstr.charCodeAt(n);
        }
        return new Blob([u8arr], { type: mime });
      };
      //将blob转换为file
      const _blobToFile = (theBlob, fileName) => {
        theBlob.lastModifiedDate = new Date();
        theBlob.name = fileName;
        return theBlob;
      };

      let files = list.map(v => {
        let blob = _dataURLtoBlob(v);
        let file = _blobToFile(blob, `img_${new Date().getTime()}.jpg`);
        return file;
      });
      return files;
    },

    /**
     * 人脸识别
     */
    // 采集人脸信息
    gatherFaceInfo() {
      console.log('开启摄像头');

      this.openMedia({
        video: {
          width: 256,
          height: 256,
          facingMode: 'user' // 移动设备上 user-前置摄像头 environment-后置摄像头
        },
        audio: false
      }).then(stream => {
        if (stream == 'fail') return;

        console.log('成功开启摄像头');

        this.faceVideo.srcObject = stream;
        this.faceVideo.play();

        // 1000ms后开始拍照
        console.log('1秒后开始采集');

        let time = setTimeout(() => {
          this.takePhoto4Face();

          clearTimeout(time); // 回收句柄
        }, 1000);
      });
    },
    // 人脸图片采集
    takePhoto4Face() {
      console.log('开始采集');

      const _takePhoto = () => {
        this.faceCtx.drawImage(
          this.faceVideo,
          0,
          0,
          this.faceCanvas.width,
          this.faceCanvas.height
        );
        const dataUrl = this.faceCanvas.toDataURL('image/jpeg', 1);
        return dataUrl;
      };

      let pictureList = []; // 照片集合
      let times = 10; // 拍照张数
      let time = setInterval(async () => {
        pictureList.push(_takePhoto());
        times--;

        if (!times) {
          console.log('采集成功');
          clearInterval(time);

          let files = this.transformToFileList(pictureList);
          let imgUrl = await this.uploadFiles(files);
          console.log(imgUrl);
          // TODO 将url提交后台校验
        }
      }, 300);
    },
    /**
     * 上传图片
     * 并发上传文件
     */
    async uploadFiles(files) {
      let imgUrl = [];
      let host = '';
      let xhrs = files.map(v => {
        const form = new FormData();
        form.append('name', 'test');
        form.append('file', v);

        imgUrl.push(`${host}/${v.name}`);

        return axios.post(host, form, { withCredentials: false });
      });

      await Promise.all(xhrs); // 用promise并发上传
      return imgUrl;
    }
  }
};
</script>

<style scoped></style>
